<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>生日概率计算原理(学生互动版)</title>
    <script src="https://cdn.socket.io/4.5.4/socket.io.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        body {
            display: flex;
            background-color: #f0f2f5;
        }
       .left-section {
            width: 50%;
            padding: 20px;
            background-color: white;
        }
       .right-section {
            width: 50%;
            padding: 20px;
            background-color: white;
            border-left: 1px solid #eee;
        }
        h1 {
            color: #1c1e21;
            margin-bottom: 20px;
            text-align: center;
        }
        table {
            width: 100%;
            border-collapse: collapse;
            margin-bottom: 20px;
            table-layout: fixed;
        }
        th, td {
            border: 1px solid #ddd;
            padding: 5px; 
            text-align: center;
            min-width: 0; 
        }
        th {
            background-color: #f8f9fa;
            color: #1c1e21;
        }
       .formula-section {
            margin-top: 20px;
        }
       .formula-item {
            margin-bottom: 10px;
            font-size: 1.1em;
            line-height: 1.6;
        }
       .math-fraction {
            display: inline-block;
            text-align: center;
            vertical-align: middle;
            margin: 0 5px;
        }
       .math-numerator {
            display: block;
            border-bottom: 1px solid #000;
            padding: 0 5px;
        }
       .math-denominator {
            display: block;
            padding: 0 5px;
        }
       .validation {
            font-size: 24px;
            margin-left: 5px;
        }
        /* 红色部分（表头第一列和左侧列）宽度设置 */
        th:first-child, td:first-child { 
            width: 80px; 
        }
        /* 蓝色部分（包含输入框的单元格）宽度设置 */
        td.blue-cell { 
            width: 60px; 
        }
        /* 填空题输入框宽度设置，可手动调节 */
       .fill-blank { 
            width: 60px; 
        }
        /* 右侧流程图UI样式 */
       .flow-container {
            display: flex;
            flex-direction: column;
            align-items: center;
        }
       .flow-node {
            margin: 5px 0;
        }
       .flow-line {
            width: 80%;
            height: 2px;
            background-color: #007BFF;
            margin: 5px 0;
        }
        button {
            padding: 8px 15px;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 4px;
            cursor: pointer;
            margin-top: 10px;
        }
        select {
            padding: 5px;
            margin: 0 5px;
        }
    </style>
</head>
<body>
    <div class="left-section">
        <h1>原理</h1>
        <table>
            <tr>
                <th>第n个同学</th>
                <th>1</th>
                <th>2</th>
                <th>......</th>
                <th>52</th>
                <th>......</th>
                <th>n(n < 365)</th>
            </tr>
            <tr>
                <td>不在同一天生日的概率</td>
                <td><span class="math-fraction">
                    <span class="math-numerator">365</span>
                    <span class="math-denominator">365</span>
                </span></td>
                <td><span class="math-fraction">
                    <span class="math-numerator">364</span>
                    <span class="math-denominator">365</span>
                </span></td>
                <td>......</td>
                <td class="blue-cell"> 
                    <input type="text" class="fill-blank" data-correct="314" placeholder="填分子">
                    <span class="validation"></span><br>365
                </td>
                <td>......</td>
                <td class="blue-cell"> 
                    <input type="text" class="fill-blank" data-correct="365 - n + 1" placeholder="填分子">
                    <span class="validation"></span><br>365
                </td>
            </tr>
        </table>
        <div class="formula-section">
            <div class="formula-item">
                52个人没有同一天生日的概率p：<br>
                <input type="radio" name="pCalculation" value="multiplication" class="single-choice" data-correct="multiplication">
                <span class="math-fraction">
                    <span class="math-numerator">365</span>
                    <span class="math-denominator">365</span>
                </span>
                ×
                <span class="math-fraction">
                    <span class="math-numerator">364</span>
                    <span class="math-denominator">365</span>
                </span>
                × …… ×
                <span class="math-fraction">
                    <span class="math-numerator">314</span>
                    <span class="math-denominator">365</span>
                </span>
                <span class="validation"></span><br>
                <input type="radio" name="pCalculation" value="addition" class="single-choice" data-correct="multiplication">
                <span class="math-fraction">
                    <span class="math-numerator">365</span>
                    <span class="math-denominator">365</span>
                </span>
                +
                <span class="math-fraction">
                    <span class="math-numerator">364</span>
                    <span class="math-denominator">365</span>
                </span>
                + …… +
                <span class="math-fraction">
                    <span class="math-numerator">314</span>
                    <span class="math-denominator">365</span>
                </span>
                <span class="validation"></span>
            </div>
            <div class="formula-item">
                没有同一天生日的概率为：<br>
                <input type="radio" name="probability" value="p" class="single-choice" data-correct="oneMinusP">p<span class="validation"></span><br>
                <input type="radio" name="probability" value="oneMinusP" class="single-choice" data-correct="oneMinusP">1 - p<span class="validation"></span>
            </div>
        </div>
    </div>

    <div class="right-section">
        <h1>计算流程图</h1>
        <div class="flow-container">
            <div class="flow-node">开始</div>
            <div class="flow-line"></div>
            <div class="flow-node">
                初始概率p=
                <input type="radio" name="initP" value="1" data-correct="1">1
                <span class="validation"></span>
                <input type="radio" name="initP" value="0" data-correct="1">0
                <span class="validation"></span>
            </div>
            <div class="flow-line"></div>
            <div class="flow-node">第n个同学不同生日的概率是: pn = (365 - n + 1)/365</div>
            <div class="flow-line"></div>
            <div class="flow-node">
                p = p 
                <select id="operation" data-correct="*">
                    <option value="*">×</option>
                    <option value="+">+</option>
                </select>
                <span class="validation"></span> pn
            </div>
            <div class="flow-line"></div>
            <div class="flow-node">
                n <= 
                <input type="text" class="fill-blank" data-correct="52" placeholder="填数字">
                <span class="validation"></span>
            </div>
            <div class="flow-line"></div>
            <div class="flow-node">
                输出52人有同一天出生的概率:
                <input type="radio" name="output" value="p" data-correct="1-p">p
                <span class="validation"></span>
                <input type="radio" name="output" value="1-p" data-correct="1-p">1 - p
                <span class="validation"></span>
            </div>
            <div class="flow-line"></div>
            <div class="flow-node">结束</div>
        </div>
        <button id="executeBtn" disabled>执行程序</button>
        <div id="resultLabel">52个人有同一天生日的概率是：<span id="resultValue"></span></div>
    </div>

    <script>
        const socket = io();
        
        // 监听教师端发送的更新
        socket.on('updateFromTeacher', (data) => {
            // 更新学生界面的状态
            if(data.type === 'radio') {
                document.querySelector(`input[name="${data.name}"][value="${data.value}"]`).checked = true;
                document.querySelector(`input[name="${data.name}"][value="${data.value}"]`).dispatchEvent(new Event('change'));
            } else if(data.type === 'text') {
                document.querySelector(`input[data-correct="${data.correct}"]`).value = data.value;
                document.querySelector(`input[data-correct="${data.correct}"]`).dispatchEvent(new Event('input'));
            } else if(data.type === 'select') {
                document.getElementById(data.id).value = data.value;
                document.getElementById(data.id).dispatchEvent(new Event('change'));
            }
        });

        document.addEventListener('DOMContentLoaded', function () {
            // 检查单个元素是否正确
            function checkElement(element) {
                if (element.tagName === 'INPUT') {
                    if (element.type === 'radio') {
                        // 获取同一组的所有单选按钮
                        const radioGroup = document.querySelectorAll(`input[name="${element.name}"]`);
                        const validationSpans = Array.from(radioGroup).map(radio => radio.nextElementSibling);
                        
                        // 重置所有验证标记
                        validationSpans.forEach(span => {
                            span.textContent = '';
                        });
                        
                        // 如果当前单选按钮被选中，显示验证结果
                        if (element.checked) {
                            const validationSpan = element.nextElementSibling;
                            validationSpan.textContent = element.value === element.dataset.correct? '✓' : '×';
                            validationSpan.style.color = element.value === element.dataset.correct? 'green' :'red';
                        }
                    } else if (element.type === 'text') {
                        const validationSpan = element.nextElementSibling;
                        const correctValue = element.dataset.correct;
                        const userInput = element.value.trim();
                        
                        if (correctValue.includes('n')) {
                            function standardizeExpr(expr) {
                                expr = expr.replace(/\s+/g, '').replace(/-/g, ' - ');
                                const terms = expr.split(/(\+|\-)/).map(t => t.trim());
                                let constant = 0;
                                let nCoeff = 0;
                                let currentOp = '+';
                                
                                terms.forEach(term => {
                                    if (term === '+' || term === '-') currentOp = term;
                                    else if (term.includes('n')) {
                                        const coeff = term.replace('n', '') || '1';
                                        nCoeff += currentOp === '+' ? parseInt(coeff) : -parseInt(coeff);
                                    } else {
                                        constant += currentOp === '+' ? parseInt(term) : -parseInt(term);
                                    }
                                });
                                
                                return `${constant} ${nCoeff >= 0? '+' : '-'} ${Math.abs(nCoeff)}n`;
                            }
                            
                            const stdUser = standardizeExpr(userInput);
                            const stdCorrect = standardizeExpr(correctValue);
                            validationSpan.textContent = stdUser === stdCorrect? '✓' : '×';
                            validationSpan.style.color = stdUser === stdCorrect? 'green' :'red';
                        } else {
                            validationSpan.textContent = userInput === correctValue? '✓' : '×';
                            validationSpan.style.color = userInput === correctValue? 'green' :'red';
                        }
                    }
                } else if (element.tagName === 'SELECT') {
                    const validationSpan = element.nextElementSibling;
                    validationSpan.textContent = element.value === element.dataset.correct? '✓' : '×';
                    validationSpan.style.color = element.value === element.dataset.correct? 'green' :'red';
                }
            }

            // 检查所有输入是否正确
            function checkAllCorrect() {
                const inputs = document.querySelectorAll('input, select');
                let allCorrect = true;
                
                inputs.forEach(input => {
                    // 只检查有值的输入（单选按钮需要选中，文本框需要有内容）
                    if (input.type === 'radio' &&!input.checked) return;
                    if (input.type === 'text' && input.value.trim() === '') return;
                    if (input.tagName === 'SELECT' && input.value === '') return;
                    
                    checkElement(input);
                    
                    if (input.type === 'radio' && input.checked && input.value!== input.dataset.correct) {
                        allCorrect = false;
                    }
                    
                    if (input.type === 'text') {
                        const correctValue = input.dataset.correct;
                        const userInput = input.value.trim();
                        
                        if (correctValue.includes('n')) {
                            function standardizeExpr(expr) {
                                expr = expr.replace(/\s+/g, '').replace(/-/g, ' - ');
                                const terms = expr.split(/(\+|\-)/).map(t => t.trim());
                                let constant = 0;
                                let nCoeff = 0;
                                let currentOp = '+';
                                
                                terms.forEach(term => {
                                    if (term === '+' || term === '-') currentOp = term;
                                    else if (term.includes('n')) {
                                        const coeff = term.replace('n', '') || '1';
                                        nCoeff += currentOp === '+' ? parseInt(coeff) : -parseInt(coeff);
                                    } else {
                                        constant += currentOp === '+' ? parseInt(term) : -parseInt(term);
                                    }
                                });
                                
                                return `${constant} ${nCoeff >= 0? '+' : '-'} ${Math.abs(nCoeff)}n`;
                            }
                            
                            const stdUser = standardizeExpr(userInput);
                            const stdCorrect = standardizeExpr(correctValue);
                            if (stdUser!== stdCorrect) allCorrect = false;
                        } else {
                            if (userInput!== correctValue) allCorrect = false;
                        }
                    }
                    
                    if (input.tagName === 'SELECT' && input.value!== input.dataset.correct) {
                        allCorrect = false;
                    }
                });
                
                return allCorrect;
            }

            // 更新按钮状态
            function updateButton() {
                const executeBtn = document.getElementById('executeBtn');
                executeBtn.disabled =!checkAllCorrect();
            }

            // 监听输入变化并发送到教师端
            const radios = document.querySelectorAll('input[type="radio"]');
            const fillBlanks = document.querySelectorAll('input[type="text"]');
            const select = document.getElementById('operation');
            
            // 发送学生操作到教师端
            function sendToTeacher(data) {
                socket.emit('studentAction', data);
            }
            
            radios.forEach(radio => {
                radio.addEventListener('change', function() {
                    checkElement(radio);
                    updateButton();
                    sendToTeacher({
                        type: 'radio',
                        name: radio.name,
                        value: radio.value
                    });
                });
            });
            
            fillBlanks.forEach(input => {
                input.addEventListener('input', function() {
                    checkElement(input);
                    updateButton();
                    sendToTeacher({
                        type: 'text',
                        correct: input.dataset.correct,
                        value: input.value
                    });
                });
            });
            
            select.addEventListener('change', function() {
                checkElement(select);
                updateButton();
                sendToTeacher({
                    type: 'select',
                    id: select.id,
                    value: select.value
                });
            });

            // 执行程序
            document.getElementById('executeBtn').addEventListener('click', function() {
                let p = 1;
                const n = 52;
                const operation = document.getElementById('operation').value;
                
                for (let i = 1; i <= n; i++) {
                    const pn = (365 - i + 1) / 365;
                    if (operation === '*') {
                        p *= pn;
                    } else {
                        p += pn;
                    }
                }
                
                const output = document.querySelector('input[name="output"]:checked').value;
                const result = output === 'p'? p : 1 - p;
                document.getElementById('resultValue').textContent = result.toFixed(3);
            });

            // 初始化验证 - 只检查已填写/已选择的内容
            document.querySelectorAll('input[type="radio"]:checked').forEach(checkElement);
            document.querySelectorAll('input[type="text"]').forEach(input => {
                if (input.value.trim() !== '') checkElement(input);
            });
            checkElement(select);
            updateButton();
        });
    </script>
</body>
</html>